---@class Battle.SceneMgr
local SceneMgr = Battle.CreateClass("SceneMgr")
Battle.SceneMgr = SceneMgr
local this = SceneMgr
function SceneMgr.OnCreate()
    this.isLoading = false
    ---@type GameObject
    this.gRoot = nil
    ---@type Transform
    this.sceneRoot = nil
    ---@type BoxCollider
    this.boxCollider = nil
    this.cameraTran = nil
    ---@type Camera
    this.camera = nil
    ---@type Transform
    this.effectRoot = nil
    ---@type Transform
    this.poolRoot = nil
    this.requestId = -1
    this.areaList = {}
    this.myBornPos = Vector3.New()
    this.myBornForward = Vector3.New()
    this.enemyBornPos = Vector3.New()
    this.enemyBornForward = Vector3.New()
    Battle.GlobalEventSystem.Register(Battle.Event.ShowPutAreaEffect,this.Event_ShowPutAreaEffect)
end
function SceneMgr.OnDestroy()
    this.isLoading = false
    this.gRoot = nil
    this.cameraCtrl = nil
    this.sceneRoot = nil
    this.cameraTran = nil
    this.camera = nil
    this.boxCollider = nil
    Battle.GlobalEventSystem.UnRegister(Battle.Event.ShowPutAreaEffect,this.Event_ShowPutAreaEffect)

end
function SceneMgr.AddChild(transform)
    if this.sceneRoot == nil then
        logError("[AddChild]场景未创建，无法添加")
        return
    end
    if transform then
        transform:SetParent(this.sceneRoot,false)
    end
end
function SceneMgr.AddEffectChild(transform)
    if this.effectRoot == nil then
        logError("[AddEffectChild]场景未创建，无法添加")
        return
    end
    if transform then
        transform:SetParent(this.effectRoot,false)
    end
end
function SceneMgr.AddPoolChild(transform)
    if this.poolRoot == nil then
        logError("[AddPoolChild]场景未创建，无法添加")
        return
    end
    if transform then
        transform:SetParent(this.poolRoot,false)
    end
end
function SceneMgr.LoadScene(scenePath,callback,tb)
    if this.isLoading then
        return
    end
    if this.requestId > 0 then
        return
    end
    UnitySceneManager.LoadScene(scenePath)
    this.isLoading = true
    this.loadedCallback = callback
    this.loadedCallbackTB = tb
end
function SceneMgr.LoadSceneAsync(scenePath,callback,tb,showLoading)
    if this.isLoading then
        return
    end
    if this.requestId > 0 then
        return
    end
    local async = UnitySceneManager.LoadSceneAsync(scenePath)
    this.isLoading = true
    this.loadedCallback = callback
    this.loadedCallbackTB = tb
    if showLoading then
        async.allowSceneActivation = false
        loadTimer = UTimer.TimeCall(function()
            if async.progress < 0.89 then
                FireEvent(UIEvent.FreshLoadingProgress, async.progress*100)
            else
                FireEvent(UIEvent.FreshLoadingProgress, 100)
                async.allowSceneActivation = true
                UTimer.Remove(loadTimer)
                loadTimer = nil
            end
        end,nil,0.1, -1)
    end
end
function this.CamaraUpdate()
    Battle.GlobalEventSystem.BroadCast(Battle.Event.CameraPosChanged)
end
function SceneMgr.InitArea()
    local tran = this.gRoot.transform
    local strList = {"left","right"}
    local area = tran:Find("area")
    for k,v in pairs(strList) do
        local go = area:Find(v)
        ---@type BoxCollider
        local box = go:GetComponent(typeof(UnityEngine.BoxCollider))
        local x,y,z = Util.GetPosition(go,nil,nil,nil)
        local width = box.size.x
        local height = box.size.z

        this.areaList[v] = {minX = x-width/2,
                            minZ = z-height/2,
                            maxX = x+width/2,
                            maxZ = z+height/2}
    end
end
---world pos
--放置区
function SceneMgr.LimitPutArea(x,y,z)
    local area = this.areaList["left"]
    x = math.min(area.maxX,x)
    x = math.max(area.minX,x)
    z = math.min(area.maxZ,z)
    z = math.max(area.minZ,z)
    return x,0,z
end

--可行走区域
---@param actor Battle.Entity
function SceneMgr.GetWorkAreaMask(actor)
    local road = 1
    if actor:IsUnitFly() then
        road = bit.bor(2^3,1)
    end
    return road
end
--当前所在区域
function SceneMgr.CheckInArea(pos)
    return Battle.AreaType.common
    --[[local mid = this.areaList["mid"]
    if pos.x > mid.maxX or pos.x < mid.minX  then
        return Battle.AreaType.common
    end
    if pos.z < mid.minZ then
        return Battle.AreaType.midUp
    end
    if pos.z > mid.maxZ then
        return Battle.AreaType.midDown
    end
    return Battle.AreaType.mid]]
end
---world pos -> local pos
---@return number,number,number
function SceneMgr.InverseTransformPoint(wx,wy,wz)
    local x,y,z = Util.InverseTransformPoint(this.sceneRoot,wx,wy,wz,0,0,0)
    return x,y,z
end
---local pos -> world pos
---@return number,number,number
function SceneMgr.TransformPoint(lx,ly,lz)
    local x,y,z = Util.TransformPoint(this.sceneRoot,lx,ly,lz,0,0,0)
    return x,y,z
end
---World pos -> Screen pos
---@return number,number,number
function SceneMgr.WorldToScreenPoint(x,y,z)
    local x,y,z = Util.WorldToScreenPoint(this.camera,x,y,z,0,0,0)
    return x,y,z
end
---@return number,number,number
function SceneMgr.ScreenToWorldPoint(x,y,z)
    local x,y,z = Util.ScreenToWorldPoint(this.camera,x,y,z,0,0,0)
    return x,y,z
end
function SceneMgr.EnableCameraMove(enable)
    if this.cameraCtrl then
        this.cameraCtrl:SetMove(enable)
    end
end
---@param rootScene RootScene
function SceneMgr.OnSceneLoaded(rootScene)
    this.myBornPos:Set(this.GetPosition(rootScene.myBornPos))
    this.enemyBornPos:Set(this.GetPosition(rootScene.enemyBornPos))
    this.myBornForward:Set(Util.GetForward(rootScene.myBornPos,nil,nil,nil))
    this.enemyBornForward:Set(Util.GetForward(rootScene.enemyBornPos,nil,nil,nil))
    closeUI(PanelNames.UILoading)
    this.camera = rootScene.mCamera
    this.cameraTran = this.camera.transform

    local root = rootScene.transform:Find("root")
    this.gRoot = root.gameObject
    local temp = GameObject.New("root")
    this.sceneRoot = temp.transform
    this.sceneRoot:SetParent(root,false)
    temp = GameObject.New("effect")
    this.effectRoot = temp.transform
    this.effectRoot:SetParent(root,false)
    temp = GameObject.New("pool")
    this.poolRoot = temp.transform
    this.poolRoot:SetParent(root,false)
    this.InitArea()

    this.putAreaEffectGo = root:Find("area/left/fangzhiquyu").gameObject
    this.putAreaEffectGo:SetActive(false)
    ---@type CameraCtrl
    --this.cameraCtrl = this.camera.gameObject:GetComponent(typeof(CameraCtrl))
    --if not this.cameraCtrl then
    --    this.cameraCtrl = this.camera.gameObject:AddComponent(typeof(CameraCtrl))
    --end
    --this.cameraCtrl:Set(this.CamaraUpdate)
    rootScene.gameObject:AddComponent(typeof(CEntityMgr))
    if this.loadedCallback then
        this.loadedCallback(this.loadedCallbackTB)
    end
end
function SceneMgr.OnExploreSceneLoaded(exploreScene)
    this.exploreSceneRoot = exploreScene
    showUI(PanelNames.UIJoyMain)
end
function SceneMgr.GetPosition(transform)
    return Util.GetPosition(transform,nil,nil,nil)
end
function SceneMgr.GetRaycastScenePos()
    local flag,wx,wy,wz = Util.Raycast(this.camera,nil,nil,nil,2^LayerMask.NameToLayer("Scene"))
    return flag ,wx,wy,wz
end
---@param args BattleEvent
function SceneMgr.Event_ShowPutAreaEffect(args)
    if this.putAreaEffectGo then
        this.putAreaEffectGo:SetActive(args.isShow)
    end
end